﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Acms.DatabaseTest.Helpers;
using System.Data.SqlClient;
using System.Data;

namespace Acms.DatabaseTest
{
    [TestClass]
    public class SiteTests
    {
        [TestMethod]
        public void GetAllTest()
        {
            using (var conn = TestConnection.Begin())
            {
                Enumerable.Range(1, 10).ToList().ForEach(i => 
                    conn.Site_Add(i, "Name " + i, "www.test" + i + ".com", true, true, i % 2 == 0 ? true : false)
                    );
                var results = conn.ExecuteProc("acms.Site_GetAll", new ParamCollection());
                Assert.AreEqual(5, results.Count);
            }
        }

        [TestMethod]
        public void GetByIdTest()
        {
            using (var conn = TestConnection.Begin())
            {
                Enumerable.Range(1, 10).ToList().ForEach(i =>
                    conn.Site_Add(i, "Name " + i, "www.test" + i + ".com", true, true, i % 2 == 0 ? true : false)
                    );
                var results = conn.ExecuteProc("acms.Site_GetById", new ParamCollection().AddInputParam("id", SqlDbType.Int, 5));
                Assert.AreEqual(1, results.Count);
                Assert.AreEqual(5, results.First()["Id"]);
            }
        }

        [TestMethod]
        public void GetByNameTest()
        {
            using (var conn = TestConnection.Begin())
            {
                Enumerable.Range(1, 10).ToList().ForEach(i =>
                    conn.Site_Add(i, "Name " + i, "www.test" + i + ".com", true, true, false)
                    );
                var results = conn.ExecuteProc("acms.Site_GetByName", new ParamCollection().AddInputParam("Name", SqlDbType.VarChar, "Name 3"));
                Assert.AreEqual(1, results.Count);
                Assert.AreEqual(3, results.First()["Id"]);
                Assert.AreEqual("Name 3", results.First()["Name"]);
            }
        }

        [TestMethod]
        public void GetByRootUrlTest()
        {
            using (var conn = TestConnection.Begin())
            {
                Enumerable.Range(1, 10).ToList().ForEach(i =>
                    conn.Site_Add(i, "Name " + i, "www.test" + i + ".com", true, true, false)
                    );
                var results = conn.ExecuteProc("acms.Site_GetByRootUrl", new ParamCollection().AddInputParam("RootUrl", SqlDbType.VarChar, "www.test4.com"));
                Assert.AreEqual(1, results.Count);
                Assert.AreEqual(4, results.First()["Id"]);
            }
        }

        [TestMethod]
        public void GetByRootUrlUsingMappingTest()
        {
            using (var conn = TestConnection.Begin())
            {
                Enumerable.Range(1, 10).ToList().ForEach(i =>
                    conn.Site_Add(i, "Name " + i, "www.test" + i + ".com", true, true, false)
                    );
                Enumerable.Range(1, 20).ToList().ForEach(i =>
                    conn.SiteMapping_Add(i, ((i - 1) % 10) + 1, "www.testmapping" + i + ".com")
                    );
                var results = conn.ExecuteProc("acms.Site_GetByRootUrl", new ParamCollection().AddInputParam("RootUrl", SqlDbType.VarChar, "www.testmapping4.com"));
                Assert.AreEqual(1, results.Count);
                Assert.AreEqual(4, results.First()["Id"]);
            }
        }

        [TestMethod]
        public void PutInsertTest()
        {
            using (var conn = TestConnection.Begin())
            {
                var sqlParams = new ParamCollection().
                        AddInputParam("id", SqlDbType.Int, null)
                        .AddInputParam("name", SqlDbType.VarChar, "test")
                        .AddInputParam("root", SqlDbType.VarChar, "testroot")
                        .AddInputParam("UseTopics", SqlDbType.Bit, true)
                        .AddInputParam("UseMenus", SqlDbType.Bit, false)
                        .AddInputParam("VersionID", SqlDbType.Timestamp, null)
                        .AddOutputParam("IdOut", SqlDbType.Int)
                        .AddOutputParam("VersionIDOut", SqlDbType.Timestamp)
                        .AddReturnParam(SqlDbType.Int);


                conn.ExecuteProc("acms.Site_Put", sqlParams);

                Assert.AreEqual(0, sqlParams.Last().Value);
                Assert.IsNotNull(sqlParams["IdOut"].Value);

                var result = conn.Site_GetAll();
                Assert.AreEqual(1, result.Count);
                Assert.AreEqual(sqlParams["IdOut"].Value, result.First()["Id"]);
                Assert.AreEqual("test", result.First()["Name"]);
                Assert.AreEqual("testroot", result.First()["Root"]);
                Assert.AreEqual(true, result.First()["UseTopics"]);
                Assert.AreEqual(false, result.First()["UseMenus"]);
                CollectionAssert.AreEqual((byte[])sqlParams["VersionIDOut"].Value, (byte[])result.First()["VersionId"]);

            }
        }

        [TestMethod]
        public void PutUpdateTest()
        {
            using(var conn = new TestConnection())
            {
                Enumerable.Range(1,10).ToList().ForEach(i =>
                    conn.Site_Add(i, "Test " + i, "Root " + i, true, false, false)
                );
                
                var versionID = (byte[])conn.Site_Get(3)["VersionId"];

                var sqlParams = new ParamCollection().
                        AddInputParam("id", SqlDbType.Int, 3)
                        .AddInputParam("name", SqlDbType.VarChar, "updated_name")
                        .AddInputParam("root", SqlDbType.VarChar, "updated_root")
                        .AddInputParam("UseTopics", SqlDbType.Bit, false)
                        .AddInputParam("UseMenus", SqlDbType.Bit, true)
                        .AddInputParam("VersionID", SqlDbType.Timestamp, versionID)
                        .AddOutputParam("IdOut", SqlDbType.Int)
                        .AddOutputParam("VersionIDOut", SqlDbType.Timestamp)
                        .AddReturnParam(SqlDbType.Int);

                conn.ExecuteProc("acms.Site_Put", sqlParams);

                Assert.AreEqual(10, conn.Site_GetAll().Count);

                var results = conn.Site_GetAll();

                for (int i = 1; i <= results.Count; i++)
                {
                    if (i != 3)
                    {
                        Assert.AreEqual(i, results[i - 1]["Id"]);
                        Assert.AreEqual("Test " + i, results[i - 1]["Name"]);
                        Assert.AreEqual("Root " + i, results[i - 1]["Root"]);
                        Assert.AreEqual(true, results[i - 1]["UseTopics"]);
                        Assert.AreEqual(false, results[i - 1]["UseMenus"]);
                    }
                    else
                    {
                        Assert.AreEqual(3, results[i- 1]["Id"]);
                        Assert.AreEqual("updated_name", results[i - 1]["Name"]);
                        Assert.AreEqual("updated_root", results[i - 1]["Root"]);
                        Assert.AreEqual(false, results[i - 1]["UseTopics"]);
                        Assert.AreEqual(true, results[i - 1]["UseMenus"]);
                        CollectionAssert.AreNotEqual(versionID, (byte[])results[i - 1]["VersionId"]);

                    }
                }
            }

        }
    }
}
